/*
 *  Copyright 2020-2025 the original author or authors.
 *  You cannot use this file unless authorized by the author.
 */

package org.ipig.search.es;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.ipig.search.IndexInfo;

/**
 * index管理
 *
 * @author <a href="mailto:comchnts@163.com">chinats</a>
 * @version $$Id$$
 * @since 1.0
 */
@Slf4j
public class IndexManger {
    /**
     * 副本数
     */
    public static final String NUMBER_OF_REPLICAS = "index.number_of_replicas";
    /**
     * 分片数
     */
    public static final String NUMBER_OF_SHARDS = "index.number_of_shards";

    /**
     * 判定索引是否存在
     *
     * @param client    IndicesAdminClient
     * @param indexName 索引名
     * @return boolean
     */
    public static boolean isExistsIndex(IndicesAdminClient client, final String indexName) {
        IndicesExistsResponse response = client.prepareExists(indexName).get();
        return response.isExists();
    }

    /**
     * 创建索引
     *
     * @param client IndicesAdminClient
     * @param info   IndexInfo
     * @return boolean
     */
    public static boolean createIndex(IndicesAdminClient client, final IndexInfo info) {
        log.debug("buildIndexMapping={}", info.buildIndexMapping());
        boolean flag = false;
        if (!isExistsIndex(client, info.getIndexName())) {
            if (info.getIndexShardsNum() <= 0) {
                CreateIndexResponse createIndexResponse = client.prepareCreate(info.getIndexName()).get();
                flag = createIndexResponse.isAcknowledged();
                log.debug("索引{}创建结果={}", info.getIndexName(), flag);
                if (Version.CURRENT.id>=8000099) {
                    if (flag && StringUtils.isNotBlank(info.buildIndexMapping())) {
                        AcknowledgedResponse putMappingResponse = client.preparePutMapping(info.getIndexName())
                                .setSource(info.buildIndexMapping(), XContentType.JSON).get();
                        flag = putMappingResponse.isAcknowledged();
                        log.debug("索引{}类型{}构建映射结果={}", info.getIndexName(), info.getIndexTypeName(), flag);
                    }
                } else {
                    if (flag && StringUtils.isNotBlank(info.getIndexTypeName())
                            && StringUtils.isNotBlank(info.buildIndexMapping())) {
                        AcknowledgedResponse putMappingResponse = client.preparePutMapping(info.getIndexName())
                                .setType(info.getIndexTypeName()).setSource(info.buildIndexMapping(), XContentType.JSON)
                                .get();
                        flag = putMappingResponse.isAcknowledged();
                        log.debug("索引{}类型{}构建映射结果={}", info.getIndexName(), info.getIndexTypeName(), flag);
                    }
                }
            } else {
                Settings settings = Settings.builder().put(NUMBER_OF_SHARDS, info.getIndexShardsNum())
                        .put(NUMBER_OF_REPLICAS, info.getIndexReplicasNum()).build();
                CreateIndexResponse createIndexResponse = client.prepareCreate(info.getIndexName())
                        .setSettings(settings).execute().actionGet();
                flag = createIndexResponse.isAcknowledged();
                log.debug("索引{}创建结果={}", info.getIndexName(), flag);

                if (Version.CURRENT.id>=8000099) {
                    if (flag && StringUtils.isNotBlank(info.buildIndexMapping())) {
                        AcknowledgedResponse putMappingResponse = client.preparePutMapping(info.getIndexName())
                                .setSource(info.buildIndexMapping(), XContentType.JSON).get();
                        flag = putMappingResponse.isAcknowledged();
                        log.debug("索引{}类型{}构建映射结果={}", info.getIndexName(), info.getIndexTypeName(), flag);
                    }
                } else {
                    if (flag && StringUtils.isNotBlank(info.getIndexTypeName())
                            && StringUtils.isNotBlank(info.buildIndexMapping())) {
                        AcknowledgedResponse putMappingResponse = client.preparePutMapping(info.getIndexName())
                                .setType(info.getIndexTypeName()).setSource(info.buildIndexMapping(), XContentType.JSON)
                                .get();
                        flag = putMappingResponse.isAcknowledged();
                        log.debug("索引{}类型{}构建映射结果={}", info.getIndexName(), info.getIndexTypeName(), flag);
                    }
                }
            }
        } else {
            log.info("indexName={} exists", info.getIndexName());
        }
        return flag;
    }

    /**
     * 位索引indexName设置mapping
     *
     * @param client IndicesAdminClient
     * @param info   IndexInfo
     * @return boolean
     */
    public static boolean setMapping(IndicesAdminClient client, final IndexInfo info) {
        if (StringUtils.isBlank(info.getIndexName()) || StringUtils.isBlank(info.getIndexTypeName())
                || StringUtils.isBlank(info.buildIndexMapping())) {
            throw new IllegalArgumentException("indexName or typeName or jsonMapping is blank.");
        }
        AcknowledgedResponse response = client.preparePutMapping(info.getIndexName()).setType(info.getIndexTypeName())
                .setSource(info.buildIndexMapping(), XContentType.JSON).get();
        return response.isAcknowledged();
    }

    /**
     * 删除索引
     *
     * @param client    IndicesAdminClient
     * @param indexName 索引名
     * @return boolean
     */
    public static boolean deleteIndex(IndicesAdminClient client, final String indexName) {
        boolean flag = true;
        if (isExistsIndex(client, indexName)) {
            AcknowledgedResponse deleteResponse = client.prepareDelete(indexName).execute().actionGet();
            flag = deleteResponse.isAcknowledged();
        } else {
            log.warn("indexName={} not found", indexName);
        }
        return flag;
    }
}